﻿using System;
using System.Runtime.Serialization;

namespace Cache.MemoryCache
{
    public class MemoryCache : ICache
    {
        private bool _isCache = true;
        private string _keyPrefix = "";

        public MemoryCache()
        {
        }

        public MemoryCache(string prefix)
        {
            _keyPrefix = prefix;
        }

        /// <summary>
        ///     Key前缀
        /// </summary>
        public string KeyPrefix
        {
            get { return _keyPrefix; }
            set { _keyPrefix = value; }
        }

        /// <summary>
        ///     是否缓存
        /// </summary>
        public bool IsCache
        {
            set { _isCache = value; }
            get { return _isCache; }
        }

        public int Count
        {
            get { return CacheItemDictionary.ItemDictionary.Count; }
        }

        /// <summary>
        ///     每隔多少分钟扫描一次
        /// </summary>
        public int IntervalMinutes
        {
            get { return CacheItemDictionary.IntervalMinutes; }
            set { CacheItemDictionary.IntervalMinutes = value; }
        }

        /// <summary>
        ///     处理多少分钟之前的元素
        /// </summary>
        public int ScavangeMinutes
        {
            get { return CacheItemDictionary.ScavangeMinutes; }
            set { CacheItemDictionary.ScavangeMinutes = value; }
        }

        /// <summary>
        ///     最大可缓存元素数
        /// </summary>
        public long MaxCount
        {
            get { return CacheItemDictionary.MaxCount; }
            set { CacheItemDictionary.MaxCount = value; }
        }

        /// <summary>
        ///     最大可使用缓存大小
        /// </summary>
        public long MaxSize
        {
            get { return CacheItemDictionary.MaxSize; }
            set { CacheItemDictionary.MaxSize = value; }
        }

        public long Size
        {
            get { return CacheItemDictionary.Size; }
        }

        public object Get(string key)
        {
            if (!IsCache)
            {
                return null;
            }
            key = KeyPrefix + key;
            if (CacheItemDictionary.ContainsKey(key))
            {
                CacheItem cacheItem = CacheItemDictionary.Get(key);
                return SerializationUtility.ToObject(cacheItem.value);
            }
            else
            {
                return null;
            }
        }

        public void Set(string key, object value)
        {
            Set(key, value, DateTime.Now.AddYears(1));
        }

        public void Set(string key, object value, int expirySeconds)
        {
            Set(key, value, DateTime.Now.AddSeconds(expirySeconds));
        }

        /// <summary>
        ///     设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiryDate"></param>
        public void Set(string key, object value, DateTime expiryDate)
        {
            if (!IsCache)
                return;

            key = KeyPrefix + key;

            if (!value.GetType().IsSerializable)
                throw new SerializationException("Object is not serializable");

            CacheItemDictionary.Add(key,
                                    new CacheItem(DateTime.Now, SerializationUtility.ToBytes(value), expiryDate));
        }

        /// <summary>
        ///     移除缓存
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            if (!IsCache)
            {
                return;
            }
            key = KeyPrefix + key;
            CacheItemDictionary.Remove(key);
        }

        /// <summary>
        ///     移除所有缓存
        /// </summary>
        /// <returns></returns>
        public int RemoveAll()
        {
            if (!IsCache)
            {
                return 0;
            }

            int interfaceCount = 0;

            interfaceCount = CacheItemDictionary.ItemDictionary.Count;
            CacheItemDictionary.Clear();

            return interfaceCount;
        }

        //public void Scavange(double minutes)
        //{
        //    //CacheItemDictionary.Scavange(minutes);
        //}

        public bool ContainsKey(string key)
        {
            if (!IsCache)
                return false;

            key = KeyPrefix + key;
            return CacheItemDictionary.ContainsKey(key);
        }

        public void Set(string key, object value, TimeSpan expiryTimeSpan)
        {
            Set(key, value, DateTime.Now.Add(expiryTimeSpan));
        }
    }
}